package com.ocom.common.utils;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.lang.management.ManagementFactory;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.*;

/**
 * 时间工具类
 * 
 * @author ocom
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYYMM = "yyyyMM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    
    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * 获取当前Date型日期
     * 
     * @return Date() 当前日期
     */
    public static Date getNowDate()
    {
        return new Date();
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     * 
     * @return String
     */
    public static String getDate()
    {
        return dateTimeNow(YYYY_MM_DD);
    }

  /**
   * 获取昨天日期, 默认格式为yyyy-MM-dd
   *
   * @return String
   */
  public static String getYesterday()
  {
    Calendar cal=Calendar.getInstance();
    cal.add(Calendar.DATE,-1);
    Date d=cal.getTime();
    SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
    return sdf.format(d);
  }

    public static final String getTime()
    {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static final String dateTimeNow()
    {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static final String dateTimeNow(final String format)
    {
        return parseDateToStr(format, new Date());
    }

    public static final String dateTime(final Date date)
    {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static final String parseDateToStr(final String format, final Date date)
    {
        return new SimpleDateFormat(format).format(date);
    }

    public static final Date dateTime(final String format, final String ts)
    {
        try
        {
            return new SimpleDateFormat(format).parse(ts);
        }
        catch (ParseException e)
        {
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static final String datePath()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str)
    {
        if (str == null)
        {
            return null;
        }
        try
        {
            return parseDate(str.toString(), parsePatterns);
        }
        catch (ParseException e)
        {
            return null;
        }
    }



    /*
     ** @author lu
     * @date 2019/9/16 13:13
     * @param [time 时间, timeFormat 时间格式]
     * @return java.lang.String
     * @description 时间转字符串
     */
    public static String getStrDate(Date time,String timeFormat) {
        SimpleDateFormat formatter = new SimpleDateFormat(timeFormat);
        String dateString = formatter.format(time);
        return dateString;
    }

    /*
     ** @author lu
     * @date 2019/9/16 13:10
     * @param [strDate, timeFormat] 时间的格式
     * @return java.util.Date
     * @description 字符串到日期类型的转换
     */
    public static Date getDate(String strDate,String timeFormat) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat(timeFormat);
        Date currentTime_2 = formatter.parse(strDate);
        return currentTime_2;
    }


    /*
     ** @author lu
     * @date 2019/9/16 13:10
     * @param [strDate, timeFormat] 时间的格式
     * @return java.util.Date
     * @description 判断日期是否是该日期月份的最后一天
     */
    public static boolean isLastDayOfMonth(String strDate,String timeFormat) {
        Calendar calendar = Calendar.getInstance();
        try {
            calendar.setTime(DateUtil.getDate(strDate,timeFormat));
            if(calendar.get(Calendar.DAY_OF_MONTH) == calendar.getActualMaximum(Calendar.DAY_OF_MONTH)) {
                return true;
            }
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return false;
    }

    /**
     * 获取当前月的上一个月
     * @return
     */
    public static String getLastMonth() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date); // 设置为当前时间
        calendar.add(Calendar.MONTH,-1);
        date = calendar.getTime();
        String accDate = format.format(date);
        return accDate;
    }

    /**
     * 获取当前月的上N个月
     * @return
     */
    public static String getLastMonth(String month,Integer last) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
        ParsePosition pos = new ParsePosition(0);
        Date date =  format.parse(month, pos);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date); // 设置为当前时间
        calendar.add(Calendar.MONTH,last * -1);
        date = calendar.getTime();
        String accDate = format.format(date);
        return accDate;
    }



    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate()
    {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }


    /**
     *@Description:获取当前月的第一天
     * @author lu
     * @return java.util.Date
     * @date 2022/10/14 9:47
     */
    public static String getFirstDate(String timeFormat)
    {
        SimpleDateFormat sdf = new SimpleDateFormat(timeFormat);
        Date date = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        //获得本月第一天
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        String firstDay = sdf.format(calendar.getTime());
        return firstDay;
    }

    /**
     * 获取某月的最后一天
     *
     */
    public static String getLastDayOfMonth(Integer year,Integer month)
    {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR,year);
        //设置月份
        cal.set(Calendar.MONTH, month);
        //获取当月最小值
        int lastDay = cal.getMinimum(Calendar.DAY_OF_MONTH);
        //设置日历中的月份，当月+1月-1天=当月最后一天
        cal.set(Calendar.DAY_OF_MONTH, lastDay-1);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String lastDayOfMonth = sdf.format(cal.getTime());
        return lastDayOfMonth;
    }

    //获取最后一天
    public static String getendDate(Date date,String timeFormat)
    {
        SimpleDateFormat sdf = new SimpleDateFormat(timeFormat);

        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        String lastDay = sdf.format(calendar.getTime());
        return lastDay;
    }
    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate)
    {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }


    public static List<String> getMonthBetween(String minDate, String maxDate) throws Exception
    {
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");// 格式化为年月
        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();
        min.setTime(sdf.parse(minDate));
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);// 设置年月日，最少3个参数
        max.setTime(sdf.parse(maxDate));
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);
        Calendar curr = min;
        while (curr.before(max))
        {
            result.add(sdf.format(curr.getTime()));
            curr.add(Calendar.MONTH, 1);
        }
        return result;
    }

    /**
     * 将长时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss
     *
     * @param strDate
     * @return
     */
    public static Date strToDate(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDate, pos);
    }

    public static Date strToDate2(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDate, pos);
    }

    public static Date strToDate3(String strDate,String formate) {
        SimpleDateFormat formatter = new SimpleDateFormat(formate);
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDate, pos);
    }

    public static Date strToDate4(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM");
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDate, pos);
    }

    public static String dateToStr(Date time) {
        SimpleDateFormat formatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        String dateString = formatter.format(time);
        return dateString;
    }

    //判断当前时间是否在时间端内
    public static boolean isInTimeFor(Date date, String strStart, String strEnd) {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");// 设置日期格式
        Date now = null;
        Date beginTime = null;
        Date endTime = null;
        try {
            now = df.parse(df.format(date));
            beginTime = df.parse(strStart);
            endTime = df.parse(strEnd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Boolean flag = belongCalendars(now, beginTime, endTime);
        return flag;
    }


    //判断当前时间是否在时间端内
    public static boolean isInTimeFor2(Date date, String strStart, String strEnd) {
        if(strStart.equals(strEnd)){
            return true;
        }
        if(strEnd.compareTo(strStart)>0){
            return isInTimeFor(date,strStart,strEnd);
        }else{
            Boolean flag = isInTimeFor(date,strStart,"23:59:59");
            if(flag){
                return flag;
            }
            return isInTimeFor(date,"00:00:00",strEnd);
        }
    }

    /**
     * 判断时间是否在时间段内
     *
     * @param nowTime
     * @param beginTime
     * @param endTime
     * @return
     */
    public static boolean belongCalendars(Date nowTime, Date beginTime, Date endTime) {
        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(beginTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if (( date.after(begin)  || date.compareTo(begin) == 0 ) && (date.before(end) || date.compareTo(end) == 0)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     *  * 获取任意时间下个月的最后一天
     *  * 描述:.
     *  * @param repeatDate * @return
     *  */
    public static String getMaxMonthDate(String repeatDate) {
        SimpleDateFormat dft = new SimpleDateFormat("yyyyMM");
        Calendar calendar = Calendar.getInstance();
        try {
            if(repeatDate!=null && !"".equals(repeatDate)) {
                calendar.setTime(dft.parse(repeatDate));
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return dft.format(calendar.getTime());
    }

    /*
     * @Description:比较两个时间或日期的大小
     * @Author: lu 
     * @Date: 2022/6/30 17:22
     * @param time1: 
     * @param time2:  
     * @return: boolean
     **/
    public static boolean compare(String time1,String time2) throws ParseException
    {
        //如果想比较日期则写成"yyyy-MM-dd"就可以了
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        //将字符串形式的时间转化为Date类型的时间
        Date a=sdf.parse(time1);
        Date b=sdf.parse(time2);

        if(a.getTime()-b.getTime()<=0){
            return true;
        }
        else{
            return false;
        }
    }

    /**
     * 根据年份获取年份下所有月份
     * @param year
     * @return
     */

    public static String[] getYearFullMonth(String year){


        String[] array = new String[12];
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR,Integer.parseInt(year));
        cal.set(Calendar.MONTH, 0);
        for(int i=0;i<12;i++){
            array[i] = sdf.format(cal.getTime());
            cal.add(Calendar.MONTH, 1);
        }
        return array;
    }

    /**
     * 校验开始时间是否大于结束时间
     *
     * @param startTime 开始时间字符串
     * @param endTime 结束时间字符串
     * @param format 格式
     * @return
     */
    public boolean checkTimeRange(String startTime, String endTime, String format) {
        try {

            SimpleDateFormat sdf = new SimpleDateFormat(format);
            Date startDate = null;
            Date endDate = null;

            startDate = sdf.parse(startTime);
            endDate = sdf.parse(endTime);

            if (startDate.after(endDate)) { //startDate是否在endTime之后，为true 表示  startTime>endTime
                return true;
            } else {
                return false;
            }
            /*
            if (startDate.getTimee()>endDate.getEndTime()) { //判断时间戳
                return true;
            } else {
               return false;
            }*/
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }


    /**
     * 计算周几 计算date对应星期几day（0-6:周日-周六）
     */
    public static Integer getWeek(Date date) {
//        String[] weeks = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();

        cal.setTime(date);

        int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;

        week_index -- ;
        if (week_index < 0) {

            week_index = 0;

        }
        return week_index;
    }


    public static int dateToWeek(String datetime) {

        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();
        Date date;
        try {
            date = f.parse(datetime);
            cal.setTime(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //一周的第几天
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return w;
    }

    /**
     * 获取当前月第一天
     * @param month
     * @return
     */
    public static String getFirstDayOfMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置月份
        calendar.set(Calendar.MONTH, month - 1);
        // 获取某月最小天数
        int firstDay = calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
        // 设置日历中月份的最小天数
        calendar.set(Calendar.DAY_OF_MONTH, firstDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String firstDayDate = sdf.format(calendar.getTime());
        return firstDayDate;
    }

    /**
     * 获取当前月最后一天
     * @param month
     * @return
     */
    public static String getLastDayOfMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置月份
        calendar.set(Calendar.MONTH, month - 1);
        // 获取某月最大天数
        int lastDay=0;
        //2月的平年瑞年天数
        if(month==2) {
            // 这个api在计算2020年2月的过程中有问题
            lastDay = calendar.getLeastMaximum(Calendar.DAY_OF_MONTH);
        }else {
            lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        }
        // 设置日历中月份的最大天数
        calendar.set(Calendar.DAY_OF_MONTH, lastDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String lastDayDate = sdf.format(calendar.getTime());
        return lastDayDate;
    }

    //指定月份的第一天
    public static LocalDate getFirstDayOfMonth(Date date) {
        LocalDate localDate = date.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();

        int year = localDate.getYear();
        int month = localDate.getMonthValue(); // 直接给出月份的数值，不需要+1

        YearMonth yearMonth = YearMonth.of(year, month);
        return yearMonth.atDay(1);
    }

    //指定月份的最后一天
    public static LocalDate getLastDayOfMonth(Date date) {
        LocalDate localDate = date.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();

        int year = localDate.getYear();
        int month = localDate.getMonthValue(); // 直接给出月份的数值，不需要+1

        YearMonth yearMonth = YearMonth.of(year, month);
        return yearMonth.atEndOfMonth();
    }

    /**
     * 开始时间和结束时间相差多少秒
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param format 格式 yyyy-MM-dd || yyyy-MM-dd HH:mm:ss
     * @return 秒
     */
    public static Long getDifferSecond(String startTime, String endTime, String format) {
        long sTime = 0;
        long eTime = 0;
        long result = 0;
        try {
            DateFormat df = new SimpleDateFormat(format);
            Date sDate = df.parse(startTime);
            Date eDate = df.parse(endTime);
            sTime = sDate.getTime();
            eTime = eDate.getTime();
            result = eTime- sTime;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result/1000;
    }

    public static void main(String[]  args){
        System.out.println(getFirstDayOfMonth(new Date()).toString());
        System.out.println(getLastDayOfMonth(new Date()).toString());
    }

    /**
     * 获取当前月的上一个月
     * @return
     */
    public static String getLastMonth2() {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date); // 设置为当前时间
        calendar.add(Calendar.MONTH,-1);
        date = calendar.getTime();
        String accDate = format.format(date);
        return accDate;
    }



}
